/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - graphics/shaders
// Copyright( c) 2015.  All Rights Reserved
//
// File:		AEShaderEffectResource.h
// Author:		Gianluca Belardelli
// Date:		31/07/2015
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AESHADEREFFECTRESOURCE_H_
#define _AESHADEREFFECTRESOURCE_H_

/// \brief
///   Class that represents a single shader effect resource as edited in the shader editor.
/// 
/// Furthermore, this class provides a cache for compiled versions of this effect.
class AEShaderEffectResource : public AEReferencedObject
{
// Members
public:
	AEShaderEffectLib *m_lpOwnerLib;
	
	char *m_lpName;
	char *m_lpDescription;
	
	VRefCountedCollection<AEShaderEffectTechnique> m_arrTechniques;
	AEShaderParamCollection m_spcParameter;
	
	// temp cache:
	VRefCountedCollection<AECompiledEffect> m_arrCachedCompiledVersions;

// Methods
public:
	/** @name Constructor/Destructor */
	/// @{
	/// \brief
	///   Constructor, sets defaults.
	AE_FORCEINLINE AEShaderEffectResource( AEShaderEffectLib *lpOwnerLib ) 
	{
		m_lpOwnerLib = lpOwnerLib;
	}
	
	/// \brief
	///   Destructor, sets defaults.
	AE_DLLIMPEXP ~AEShaderEffectResource( void );
	
	/// \brief
	///   Returns the shader library that this effect resource belongs to.
	AE_FORCEINLINE AEShaderEffectLib *GetOwnerEffectLib( void ) const 
	{ 
		return m_lpOwnerLib; 
	}
	
	/// @}
	/** @name Build Helpers */
	/// @{
	/// \brief
	///   Creates a new technique resource attached to this effect.
	AE_DLLIMPEXP AEShaderEffectTechnique *CreateNewTechnique( void ) 
	{ 
		AEShaderEffectTechnique *lpTec = new AEShaderEffectTechnique(); 
		m_arrTechniques.Add( lpTec ); 
		return lpTec;
	}
	
	/// \brief
	///   Evaluates a bitmask for platforms used in this effect. The bit index per platform corresponds to its enum value in VTargetPlatform_e.
	AE_FORCEINLINE AEINT32 GetRelevantPlatformMask( void ) const
	{
		AEINT32 nMask = 0;
		for( AEINT32 i = 0; i < m_arrTechniques.Count(); i++ )
			nMask |= m_arrTechniques.GetAt(i)->GetRelevantPlatformMask();
		return nMask;
	}
	
	/// @}
	/** @name Effect Compilation */
	/// @{
	/// \brief
	///   Creates a compiled instance of this effect and adds it to the cache.
	/// 
	/// If there is a previously compiled version that used the same parameter string, this
	/// instance will be returned.
	/// 
	/// The effect will try to compile all its techniques.
	/// 
	/// This function is provided through the global Vision::Shaders.CreateEffect function.
	/// 
	/// \param szParamString
	///   Parameter string with (varname)=(value) pairs that is used to modify the compiled shaders,
	///   e.g. "Color=1,1,1,0;Glow=0.5;"
	/// 
	/// \param instanceManager
	///   Shader instance manager that keeps track of new shader instances that are created during
	///   this process.
	/// 
	/// \param iFlags
	///   Additional flags for creating the effect. Supported bit constants are:
	///   \li EFFECTCREATEFLAG_NONE: No specific flags,
	/// 
	///   \li EFFECTCREATEFLAG_FORMODELS: The vertex shader for models should be used (if available),
	/// 
	///   \li EFFECTCREATEFLAG_FORCEUNIQUE: If set, both the effect instance and the shader pass instances
	///     are neither taken from the cache nor re-used for other compiling operations. 
	/// 
	/// \param pLog
	///   Optional log interface that will receive error/warning/info messages that occur during
	///   compiling.
	/// 
	/// \return
	///   BOOL bResult : TRUE if successful.
	AE_DLLIMPEXP AECompiledEffect *CompileEffect( const char *lpParamString, AECompiledShaderManager &refInstanceManager, AEINT32 iFlags = EFFECTCREATEFLAG_NONE, hkvLogInterface* pLog = hkvGlobalLog::GetInstance() );
	
	/// \brief
	///   Helper function to find a compiled effect version that has been generated with the passed
	///   parameter string.
	/// 
	/// This function performs a simple case-insensitive string match rather than analyzing the actual string parameters.
	/// 
	/// \param szParamString
	///   Parameter string to find a compiled version for.
	/// 
	/// \return
	///   AECompiledEffect *pEffect : Compiled instance that has a parameter string corresponding to the passed one. NULL if there is no match.
	AE_DLLIMPEXP AECompiledEffect *FindCompiledVersion( const char *lpParamString ) const;
	
	/// \brief
	///   Resets the cache of compiled effect variants.
	AE_DLLIMPEXP void FreeCompiledEffects( void ) 
	{
		m_arrCachedCompiledVersions.Clear();
	}
	
	/// \brief
	///   Internal function
	AE_DLLIMPEXP void OnDetachFromLib( void );
	
	/// \brief
	///   Adds the inclusion tags given by effect parameters (if any)
	AE_DLLIMPEXP void AddEffectParameterInclusionTags( AETechniqueConfig **lplpConfigs, AEUINT32 uiNumConfigs, const char *const lpParamString ) const;
	
	/// \brief
	///   Returns the name of the effect.
	AE_FORCEINLINE const char *GetName( void ) const
	{
		return m_lpName;
	}
	/// @}
};

#include "AEShaderEffectResource.inl"

#endif // _AESHADEREFFECTRESOURCE_H_
